App.require(["htmlTool"], function (htmlTool) {
    var app = App.getCurrent();

    app.defineComponent("str-stepper", {
        _recomputedOption: function (options, value) {
            var property = this.property;
            var index = 0, isComplete = true;
            for (var i = 0; i < options.length; i++) {
                var option = options[i];
                if (option.value === value) {
                    index = i;
                    isComplete = false;
                    option.state = "ready";
                    option.class = "str-stepper-item-active";
                    option.icon = option.activeicon || property.activeicon;
                }
                else {
                    if (isComplete) {
                        option.state = "ready";
                        option.class = "str-stepper-item-complete";
                        option.icon = option.completeicon || property.completeicon;
                    }
                    else {
                        if (property.showall) option.state = "ready";
                        else option.state = "";
                        option.class = "str-stepper-item-uncomplete";
                        option.icon = option.uncompleteicon || property.uncompleteicon;
                    }
                }
            }
        },
        _computeOption: function (value, title, content, option, str, state) {
            var option = option || {};
            option.value = value;
            option.title = title;
            option.content = content;
            option.icon = option[str + 'icon'] || this.property[str + 'icon'];
            option.state = state;
            option.class = "str-stepper-item-" + state;
            return option;
        },
        _getIndex: function (value) {
            var options = this.data.options, index = -1;
            for (var i = 0; i < options.length; i++) {
                if (options[i].value === value) {
                    index = i;
                    break;
                }
            }
            return index;
        },
        _getOptionByValue: function (value) {
            var options = this.data.options;
            for (var i = 0; i < options.length; i++) {
                if (options[i].value === value) return options[i];
            }
            return null;
        },
        appendOption: function (value, title, content, option, feeback) {
            var option = this._computeOption(value, title, content, value, option, "uncomplete", "");
            var that = this;
            this.insertAdjacentHTML(this.domList.container, this.data.liHTML, "beforeend", function () {
                that.data.options.push(option);
                if (typeof feeback === "function") feeback();
            }, { step: option });
        },
        insertBefore: function (oldValue, value, title, content, option, feeback) {
            var valueIndex = this._getIndex(this.property.value),
                insertIndex = this._getIndex(oldValue);

            if (insertIndex === -1) return this.appendOption(value, title, content, option, feeback);
            var option = null;
            if (valueIndex >= insertIndex) option = this._computeOption(value, title, content, option, "complete", "ready");
            else option = this._computeOption(value, title, content, option, "uncomplete", "");

            var that = this, container = this.domList.container;
            var stepperItem = container.querySelector("[data-value='" + oldValue + "']");
            this.insertAdjacentHTML(stepperItem, this.data.liHTML, "beforebegin", function () {
                that.data.options.splice(insertIndex, 0, option);
                if (typeof feeback === "function") feeback();
            }, { step: option })
        },
        removeOption: function (value) {
            var stepperItem = container.querySelector("[data-value='" + value + "']");
            if (stepperItem) {
                var range = document.createRange();
                range.selectNode(stepperItem);
                this.removeRange(range);
                range.detach();
            }
        },
        _getComponentInDom: function (dom) {
            var components = this.components;
            for (var i = 0; i < components.length; i++) {
                if (dom.contains(components[i].nodes[0])) return components[i];
            }
            return null;
        },
        changeOption: function (value, title, content, opt, feeback) {
            opt = opt || {};
            var stepperItem = container.querySelector("[data-value='" + value + "']");
            var option = this._getOptionByValue(value);
            if (option) {
                var strIcon = this._getComponentInDom(stepperItem),
                    titleDom = stepperItem.querySelector(".stepper-title"),
                    contentDom = stepperItem.querySelector(".stepper-content");

                titleDom.textContent = title;
                if (contentDom) contentDom.innerHTML = content;
                var valueIndex = this._getIndex(this.property.value),
                    insertIndex = this._getIndex(value), iconName;
                if (valueIndex > insertIndex) iconName = option.completeicon || this.property.completeicon;
                else if (insertIndex > valueIndex) iconName = option.uncompleteicon || this.property.uncompleteicon;
                else iconName =  option.activeicon || this.property.activeicon;

                strIcon.changeIcon(iconName, function () {
                    option.title = title;
                    option.content = content;
                    for (var key in opt) {
                        option[key] = opt[key];
                    }
                    if (typeof feeback === "function") feeback();
                })
            }
        },
        render: function (next) {
            this.computeData();
            this.fetchAll(["./li.html", "./index.html"], function (textList) {
                this.data.liHTML = textList[0];
                next(this.renderHTML(textList[1].replace("{{liHTML}}", this.data.liHTML)));
            })
        },
        getDomObj: function () {
            this.attachDom('[role="stepper"]', "container")
                .attachEvent("container", "iconclick", this.clickHandler, false);
        },
        clickHandler: function(ev) {
            var target = ev.target;
            var stepperItem = Component.getNodeName(target,"DIV");
            var value = stepperItem.dataset.value;
            this.dispatchCustomEvent("stepperclick", {
                component: this,
                event: ev.detail.event,
                value: value
            });
        },
        computeData: function () {
            var property = this.property;
            property.direction = property.direction || "row";
            this.data.options = htmlTool.getOptions(this.slot);
            property.value = property.value || this.data.options[0].value;
            property.activeicon = property.activeicon || "arrow-right-bold-circle";
            property.completeicon = property.completeicon || "check-circle";
            property.uncompleteicon = property.uncompleteicon || "alert-circle";
            property.class = property.class  || "";
            property.showall = typeof property.showall === "undefined" ? "" : "showall";
            this._recomputedOption(this.data.options, property.value);
            this.data.propertystr = this.createPropertyStr({
                class: property.class,
                direction: property.direction
            })
        },
        get className() {
            return this.property.class;
        },
        set className(value) {
            if (this.property.class == value) return;
            this.domList.container.className = value;
            this.property.class = value;
        },
        get value() {
            return this.property.value;
        },
        set value(val) {
            if (val === this.property.value) return;
            var index = this._getIndex(val),
                currentIndex = this._getIndex(this.property.value);

            if (index === -1) return;
            var children = this.domList.container.children,
                options = this.data.options;
            
            if (index > currentIndex) {
                for (var i = currentIndex ; i <= index; i++) {
                    var item = children[i], 
                        component = this._getComponentInDom(item),
                        option = options[i],
                        icon = i === index ? (option.activeicon || this.property.activeicon) : (option.completeicon || this.property.completeicon);
                        oldClass = i === currentIndex ? "str-stepper-item-active" : "str-stepper-item-uncomplete";
                        newClass = i === index ? "str-stepper-item-active" : "str-stepper-item-complete";

                    option.class = newClass;
                    item.classList.remove(oldClass);
                    item.classList.add(newClass);
                    component.icon = icon;
                    if (i !== currentIndex) {
                        option.state = true;
                        var div = document.createElement("div");
                        div.className = "stepper-content";
                        div.innerHTML = option.content;
                        item.appendChild(div);
                    }
                }
            }
            else {
                for (var i = index ; i <= currentIndex; i++) {
                    var item = children[i], 
                        component = this._getComponentInDom(item),
                        option = options[i],
                        icon = i === index ? (option.activeicon || this.property.activeicon) : (option.uncompleteicon || this.property.uncompleteicon);
                        oldClass = i === currentIndex ? "str-stepper-item-active" : "str-stepper-item-complete";
                        newClass = i === index ? "str-stepper-item-active" : "str-stepper-item-uncomplete";

                    option.class = newClass;
                    item.classList.remove(oldClass);
                    item.classList.add(newClass);
                    component.icon = icon;
                    if (i !== index) {
                        var content = item.querySelector(".stepper-content");
                        content.parentNode.removeChild(content);
                    }
                }
            }
            this.property.value = val;
        },
        get direction() {
            return this.property.direction;
        },
        set direction(value) {
            if (value === this.property.direction) return;
            this.domList.container.setAttribute("direction", value);
            this.property.direction = value;
        },
        get activeicon() {
            return this.property.activeicon;
        },
        set activeicon(value) {
            if (value === this.property.activeicon) return;
            var stepperItem = this.domList.container.querySelector("[data-value='" + this.property.value + "']");
            var component = this._getComponentInDom(stepperItem);
            component.icon = value;
            this.property.activeicon = value;
        },
        get completeicon() {
            return this.property.completeicon;
        },
        set completeicon(value) {
            if (value === this.property.completeicon) return;
            var index = this._getIndex(this.property.value), 
                children = this.domList.container.children;
            for (var i = 0; i < index - 1; i++) {
                var component = this._getComponentInDom(children[i]);
                component.icon = value;
            }
            this.property.completeicon = value;
        },
        get uncompleteicon() {
            return this.property.uncompleteicon;
        },
        set uncompleteicon(value) {
            if (value === this.property.uncompleteicon) return;
            var index = this._getIndex(this.property.value), 
                children = this.domList.container.children;
            for (var i = index + 1; i < children.length; i++) {
                var component = this._getComponentInDom(children[i]);
                component.icon = value;
            }
            this.property.uncompleteicon = value;
        }
    })
})